package org.jboss.resteasy.test.crypto.resource;
import org.jboss.resteasy.annotations.security.doseta.After;
import org.jboss.resteasy.annotations.security.doseta.Signed;
import org.jboss.resteasy.annotations.security.doseta.Verify;
import org.jboss.resteasy.security.doseta.DKIMSignature;
import org.jboss.resteasy.security.doseta.DosetaKeyRepository;
import org.jboss.resteasy.security.doseta.Verification;
import org.jboss.resteasy.spi.MarshalledEntity;
import org.jboss.resteasy.util.Base64;
import org.jboss.resteasy.util.ParameterParser;
import org.junit.Assert;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SignatureException;
import java.util.HashMap;
@Path("/signed")
public class SigningResource {
public static KeyPair keys;
public static DosetaKeyRepository repository;
public static PrivateKey badKey;
static {
repository = new DosetaKeyRepository();
repository.setKeyStorePath("test.jks");
repository.setKeyStorePassword("password");
repository.setUseDns(false);
repository.start();
PrivateKey privateKey = repository.getKeyStore().getPrivateKey("test._domainKey.samplezone.org");
if (privateKey == null) {
throw new RuntimeException("Private Key is null!!!");
}
PublicKey publicKey = repository.getKeyStore().getPublicKey("test._domainKey.samplezone.org");
keys = new KeyPair(publicKey, privateKey);
try {
KeyPair keyPair = KeyPairGenerator.getInstance("RSA").generateKeyPair();
badKey = keyPair.getPrivate();
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("Unable to generate new RSA key pair", e);
}
}
@DELETE
@Path("request-only")
public Response deleteRequestOnly(@Context HttpHeaders headers,
@Context UriInfo uriInfo,
@HeaderParam(DKIMSignature.DKIM_SIGNATURE) DKIMSignature signature) {
Assert.assertNotNull(signature);
Verification verification = new Verification(keys.getPublic());
verification.setBodyHashRequired(false);
verification.getRequiredAttributes().put("method", "GET");
verification.getRequiredAttributes().put("uri", uriInfo.getPath());
try {
verification.verify(signature, headers.getRequestHeaders(), null, keys.getPublic());
} catch (SignatureException e) {
throw new RuntimeException(e);
}
String token = signature.getAttributes().get("token");
signature = new DKIMSignature();
signature.setDomain("samplezone.org");
signature.setSelector("test");
signature.setPrivateKey(keys.getPrivate());
signature.setBodyHashRequired(false);
signature.getAttributes().put("token", token);
return Response.ok().header(DKIMSignature.DKIM_SIGNATURE, signature).build();
}
@GET
@Produces("text/plain")
@Path("bad-signature")
public Response badSignature() throws Exception {
DKIMSignature signature = new DKIMSignature();
signature.setDomain("samplezone.org");
signature.setSelector("test");
signature.sign(new HashMap<>(), "hello world".getBytes(), keys.getPrivate());
byte[] sig = {0x0f, 0x03};
String encodedBadSig = Base64.encodeBytes(sig);
ParameterParser parser = new ParameterParser();
String s = signature.toString();
String header = parser.setAttribute(s.toCharArray(), 0, s.length(), ';', "b", encodedBadSig);
signature.setSignature(sig);
return Response.ok("hello world").header(DKIMSignature.DKIM_SIGNATURE, header).build();
}
@GET
@Produces("text/plain")
@Path("bad-hash")
public Response badHash() throws Exception {
DKIMSignature signature = new DKIMSignature();
signature.setDomain("samplezone.org");
signature.setSelector("test");
signature.sign(new HashMap<>(), "hello world".getBytes(), keys.getPrivate());
return Response.ok("hello").header(DKIMSignature.DKIM_SIGNATURE, signature.toString()).build();
}
@GET
@Produces("text/plain")
@Path("manual")
public Response getManual() {
DKIMSignature signature = new DKIMSignature();
signature.setSelector("test");
signature.setDomain("samplezone.org");
Response.ResponseBuilder builder = Response.ok("hello");
builder.header(DKIMSignature.DKIM_SIGNATURE, signature);
return builder.build();
}
@GET
@Path("header")
@Produces("text/plain")
public Response withHeader() {
Response.ResponseBuilder builder = Response.ok("hello world");
builder.header("custom", "value");
DKIMSignature signature = new DKIMSignature();
signature.setSelector("test");
signature.setDomain("samplezone.org");
signature.addHeader("custom");
builder.header(DKIMSignature.DKIM_SIGNATURE, signature);
return builder.build();
}
@GET
@Signed(selector = "test", domain = "samplezone.org")
@Produces("text/plain")
public String hello() {
return "hello world";
}
@POST
@Consumes("text/plain")
@Verify
public void post(@HeaderParam(DKIMSignature.DKIM_SIGNATURE) DKIMSignature signature, String input) {
Assert.assertNotNull(signature);
Assert.assertEquals(input, "hello world");
}
@POST
@Consumes("text/plain")
@Path("verify-manual")
public void verifyManual(@HeaderParam(DKIMSignature.DKIM_SIGNATURE) DKIMSignature signature, @Context HttpHeaders headers, MarshalledEntity<String> input) throws Exception {
Assert.assertNotNull(signature);
Assert.assertEquals(input.getEntity(), "hello world");
signature.verify(headers.getRequestHeaders(), input.getMarshalledBytes(), keys.getPublic());
}
@GET
@Signed(selector = "test", domain = "samplezone.org",
timestamped = true)
@Produces("text/plain")
@Path("stamped")
public String getStamp() {
return "hello world";
}
@GET
@Signed(selector = "test", domain = "samplezone.org",
expires = @After(seconds = 1))
@Produces("text/plain")
@Path("expires-short")
public String getExpiresShort() {
return "hello world";
}
@GET
@Signed(selector = "test", domain = "samplezone.org",
expires = @After(minutes = 1))
@Produces("text/plain")
@Path("expires-minute")
public String getExpiresMinute() {
return "hello world";
}
@GET
@Signed(selector = "test", domain = "samplezone.org",
expires = @After(hours = 1))
@Produces("text/plain")
@Path("expires-hour")
public String getExpiresHour() {
return "hello world";
}
@GET
@Signed(selector = "test", domain = "samplezone.org",
expires = @After(days = 1))
@Produces("text/plain")
@Path("expires-day")
public String getExpiresDay() {
return "hello world";
}
@GET
@Signed(selector = "test", domain = "samplezone.org",
expires = @After(months = 1))
@Produces("text/plain")
@Path("expires-month")
public String getExpiresMonth() {
return "hello world";
}
@GET
@Signed(selector = "test", domain = "samplezone.org",
expires = @After(years = 1))
@Produces("text/plain")
@Path("expires-year")
public String getExpiresYear() {
return "hello world";
}
@GET
@Path("nobody")
@Consumes("text/plain")
@Verify(bodyHashRequired = false)
public String get(@HeaderParam(DKIMSignature.DKIM_SIGNATURE) DKIMSignature signature) {
Assert.assertNotNull(signature);
return "xyz";
}
}